package org.mcflier.appuntamento.core;

import java.util.HashMap;
import java.util.Map;

import org.mcflier.appuntamento.core.exception.ModulesException;
import org.mcflier.appuntamento.core.modules.IModule;

public class Factory {
	
	public static final String MODULE_UPDATER = "org.mcflier.appuntamento.core.updater.UpdatesManager";
	public static final String MODULE_I18N = "org.mcflier.appuntamento.i18n.I18N";
	public static final String MODULE_PROPERTIES = "org.mcflier.appuntamento.core.properties.PropertiesManager";
	public static final String MODULE_LOGGER = "org.mcflier.appuntamento.core.logger.LoggerManager";
	public static final String MODULE_MODULES = "org.mcflier.appuntamento.core.modules.ModulesManager";
	public static final String MODULE_JDBC = "org.mcflier.appuntamento.io.driver.db.JDBCDriver";
	public static final String MODULE_IMDB = "org.mcflier.appunamento.io.driver.imdb.IMDBDriver";
	public static final String MODULE_RSS_IMDB = "org.mcflier.appuntamento.io.driver.rss.imdb.RssImdbDriver";
	public static final String MODULE_RSS_TORRENT = "org.mcflier.appuntamento.io.driver.rss.torrent.TorrentAggregator";
	
	private Map<String, IModule> modules;
	
	private static Factory instance;
	
	static{
		instance = null;
	}
	
	public static Factory getInstance(){
		if(instance == null)
			instance = new Factory();
		
		return instance;
	}
	
	private Factory(){
		this.modules = new HashMap<String, IModule>();
	}
	
	public IModule getModuleInstance(String modulePath) throws ModulesException{
		if(modulePath == null)
			throw new NullPointerException("Module path must not be null");
		
		IModule module = this.modules.get(modulePath);
		if(module == null){
			try {
				module = (IModule)Class.forName(modulePath).newInstance();
				this.modules.put(modulePath, module);
			} catch (InstantiationException e) {
				throw new ModulesException("Error creating the module '"+modulePath+"'. This class type cannot be instantiated", e);
			} catch (IllegalAccessException e) {
				throw new ModulesException("Error creating the module '"+modulePath+"'. This class must have an accessible empty constructor", e);
			} catch (ClassNotFoundException e) {
				throw new ModulesException("Error creating the module '"+modulePath+"'. This classpath doesn't represent an existing class", e);
			}
		}
		
		return module;
	}
}